home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------
- ** DATES.C
- **
- ** Written By: Al Gifford
- **
- ** March 26, 1993
- **
- ** (c)Copyright 1993 All Rights Reserved
- **
- ** This collection of functions can greatly simplify any programming
- ** you need to do which involves the use of dates. Nothing is asked in
- ** return for using this code other than to give credit where credit is
- ** due. If you use any portion of this code, or derive ideas from it,
- ** you must make mention of that fact in your documentation (written or
- ** electronic) and/or in the program itself. Failure to do so is
- ** plagiarism and is in violation of the Copyright laws.
- */
-
- #include<stdio.h>
- #include<dos.h>
- #include<conio.h>
- #include<string.h>
- #include<stdlib.h>
-
- short Calendar(struct date d);
- struct date ConvertGregorian(long JulianDate);
- unsigned short ConvertJulian(char day,char month,short year);
- short CountLeapYear(short year1,short year2);
- short DaysInMonth(char month,short year);
- char DayOfWeek(char day,char month,short year);
- short DayOfYear(char day,char month,short year);
- char IsValidDate(char day,char month,short year);
- short LeapYear(short year);
- char *MonthName(char month);
- struct date ParseDate(char *dateString);
- void RevVideo(void);
- char *WeekdayName(char weekday);
-
- void main(void)
- {
- struct date d;
- unsigned short num;
- char dateString[40];
- char shortMonth[4];
-
- clrscr();
- getdate(&d);
- printf("\t\t\tDATE FUNCTIONS DEMONSTRATION\n\n");
- printf("The current year is: %d\n",d.da_year);
- printf("The current day is: %d\n",(short)d.da_day);
- printf("The current month is: %d, which is %s.\n",(short)d.da_mon,MonthName(d.da_mon));
- num = ConvertJulian(d.da_day,d.da_mon,d.da_year);
- printf("The Julian Date is %u.\n",num);
- d = ConvertGregorian(num);
- printf("Converted back to Gregorian is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
- num = CountLeapYear(d.da_year, 1900);
- printf("There were %u leap years between 1900 and %d.\n",num,d.da_year);
- num = DaysInMonth(d.da_mon,d.da_year);
- printf("This month has %u days.\n",num);
- num = DayOfWeek(d.da_day,d.da_mon,d.da_year);
- printf("(Sunday=0 - Saturday=6) Today is %u, which is %s.\n",num,WeekdayName((char)num));
- num = DayOfYear(d.da_day,d.da_mon,d.da_year);
- printf("Today is day %u of %d.\n",num,d.da_year);
- num = IsValidDate(d.da_day,d.da_mon,d.da_year);
- printf("The date entered was");
- if(!(num))
- printf(" not");
- printf(" valid.\n");
- num = LeapYear(d.da_year);
- printf("This year is");
- if(!(num))
- printf(" not");
- printf(" a leapyear.\n");
- num = (unsigned)d.da_year / 100 + 1;
- printf("We are in the %u",num);
- if(num % 10 == 1)
- printf("st");
- if(num % 10 == 2)
- printf("nd");
- if(num % 10 == 3)
- printf("rd");
- else
- printf("th");
- printf(" century.\n");
- printf("\nPress <Enter> to continue\n");
- getch();
- clrscr();
- sprintf(dateString,"%d/%d/%d",(short)d.da_mon,(short)d.da_day,d.da_year);
- printf("Todays date as a string: %s\n",dateString);
- d = ParseDate(dateString);
- printf("Converted back to a date structure is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
- strncpy(shortMonth,MonthName(d.da_mon),3);
- shortMonth[3] = '\0';
- strcpy(shortMonth,strupr(shortMonth));
- sprintf(dateString,"%d%s%d",(short)d.da_day,shortMonth,d.da_year - d.da_year / 100 * 100);
- printf("A more difficult date string: %s\n",dateString);
- d = ParseDate(dateString);
- printf("Converted back to a date structure is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
- sprintf(dateString,"Today's date is %s %d, %d",MonthName(d.da_mon),(short)d.da_day,d.da_year);
- printf("An even messier date string: %s\n",dateString);
- d = ParseDate(dateString);
- printf("Converted back to a date structure is YR:%d DA:%d MO:%d.\n",d.da_year,(short)d.da_day,(short)d.da_mon);
- gotoxy(21,12);
- Calendar(d);
- }
-
- struct date ConvertGregorian(long JulianDate)
- /*----------------------------------------------------------------------
- ** Function returns Gregorian date using the DOS.H date structure.
- ** Julian Date is number of Days since January 1, 1900 (Day 1).
- */
- {
- short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
- short numDays;
- struct date d;
- d.da_mon = 1;
-
- d.da_year = (short)(JulianDate / 365.2475 + 1900);
- numDays = JulianDate - (d.da_year - 1900) * 365 - CountLeapYear(d.da_year,1900);
- while(DAYS[d.da_mon + 1] < numDays)
- d.da_mon++;
- d.da_day = numDays - DAYS[d.da_mon];
- return(d);
- } /* end of ConvertJulian */
-
-
- unsigned short ConvertJulian(char day,char month,short year)
- /*----------------------------------------------------------------------
- ** Function returns number of days for Julian date.
- ** Julian Date is number of Days since January 1, 1900 (Day 1).
- */
- {
- short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
- long numDays;
-
- numDays = DAYS[month] + day;
- if(LeapYear(year) && month > 2)
- numDays++;
- numDays += ((year - 1900) * 365 + CountLeapYear(year,1900));
- return(numDays);
- } /* end of ConvertJulian */
-
- short CountLeapYear(short year1,short year2)
- {
- /*----------------------------------------------------------------------
- ** Function counts number of leapyears between two years.
- ** Years must have all 4 digits.
- */
- short count = 0;
- short small;
- short large;
-
- small = year1 < year2 ? year1 : year2;
- large = year1 > year2 ? year1 : year2;
- for(small = small;small < large;small++)
- {
- if(LeapYear(small))
- count++;
- }
- return(count);
- } /* end of CountLeapYear */
-
- short DaysInMonth(char month,short year)
- /*----------------------------------------------------------------------
- ** Function returns the number of days in a given month.
- ** The month is 1-12 and the year must have all 4 digits.
- */
- {
- short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
- char leapDay;
-
- if(month == 2 && LeapYear(year))
- leapDay = 1;
- else
- leapDay = 0;
-
- return(DAYS[month + 1] - DAYS[month] + leapDay);
- } /* end of DaysInMonth */
-
- char DayOfWeek(char day,char month,short year)
- /*----------------------------------------------------------------------
- ** Function returns the day of the week (0-6 : Sunday-Saturday).
- */
- {
- return(ConvertJulian(day,month,year) % 7);
- } /* end of DayOfWeek */
-
- short DayOfYear(char day,char month,short year)
- /*----------------------------------------------------------------------
- ** Function returns number of days for date in current year.
- */
- {
- short DAYS[] = {0,0,31,59,90,120,151,181,212,243,273,304,334,365};
- short numDays;
-
- numDays = DAYS[month] + day;
- if(LeapYear(year) && month > 2)
- numDays++;
- return(numDays);
- } /* end of DayOfYear */
-
- char IsValidDate(char day,char month,short year)
- /*----------------------------------------------------------------------
- ** Function returns 1 if date is valid, otherwise returns 0.
- ** Note: Dates earlier than 1900 are not supported by these functions.
- */
- {
- if(year < 1900)
- return(0);
- if(month > 12 || month < 1)
- return(0);
- if(day > DaysInMonth(month,year) || day < 1)
- return(0);
- else
- return(1);
- } /* end of IsValidDate */
-
- short LeapYear(short year)
- /*----------------------------------------------------------------------
- ** Function returns true (1) if year (all 4 digits) is a leap year,
- ** otherwise it returns false(0).
- */
- {
- if(!(year % 4) && (year % 100 || !(year % 400)))
- return(1);
- else
- return(0);
- } /* end of LeapYear */
-
- char *MonthName(char month)
- {
- /*-------------------------------------------------------------------------
- ** Arrays to convert numbers to words.
- **
- ** Helpful hints:
- ** To get abbreviations use strncpy() for desired length.
- ** To get upper case use strupr().
- ** To get lower case use strlwr().
- */
- char *MONTHNAME[] = {"","January","February","March","April","May","June","July","August","September","October","November","December"};
- return(MONTHNAME[month]);
- } /* end of MonthName */
-
- struct date ParseDate(char *dateString)
- /*----------------------------------------------------------------------
- ** Psuedo-intelligent date parsing function which handles common date
- ** formats including alpha and numeric months, in many different date
- ** styles. The function assumes that a year value of less than 100
- ** is actually a 2 character abbreviation and will add the current
- ** century to the returned year value. The function also assumes that
- ** the month will preceed the day, and that both will preceed the
- ** year. While this is only a problem for the month and day if the
- ** month and day are both numeric, for non-US standard date formats,
- ** the month and day will need to be swapped if the day value is 12 or
- ** less.
- **
- ** Note - If an alpha representation of the month is used, the
- ** function will enter the month and day values correctly regardless
- ** of the order in which they appear in the date string.
- */
- {
- typedef enum{
- LETTER, DIGIT, SPECIAL
- } CHAR_CODE;
-
- CHAR_CODE CHARTABLE[256];
- struct date d;
- short ch;
- char *token;
- short tokench;
- short number;
- char *cp = dateString;
- short CENTURY;
- char *MONTHSTRING = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
-
- /*----------------------------------------------------------------------
- ** Malloc space for token.
- */
- if((token = (char *)malloc(strlen(dateString + 1))) == NULL)
- printf("ERROR: Out of Memory.\n");
-
- /*----------------------------------------------------------------------
- ** Initialize character table.
- */
- for (ch = 0 ; ch < 256; ++ch) CHARTABLE[ch] = SPECIAL;
- for (ch = '0'; ch <= '9'; ++ch) CHARTABLE[ch] = DIGIT;
- for (ch = 'A'; ch <= 'Z'; ++ch) CHARTABLE[ch] = LETTER;
-
- getdate(&d);
- CENTURY = d.da_year / 100 * 100;
- d.da_day = 0;
- d.da_mon = 0;
- d.da_year = 0;
-
- dateString = strupr(dateString);
-
- while(cp - dateString < strlen(dateString))
- {
- tokench = 0;
- ch = *cp;
- switch(CHARTABLE[ch]){
- case LETTER:
- while(CHARTABLE[ch] == LETTER)
- {
- token[tokench] = ch;
- cp++;
- tokench++;
- ch = *cp;
- }
- token[tokench]='\0';
- break;
- case DIGIT:
- while(CHARTABLE[ch] == DIGIT)
- {
- token[tokench] = ch;
- cp++;
- tokench++;
- ch = *cp;
- }
- token[tokench]='\0';
- break;
- default:
- cp++;
- break;
- }
- if(tokench && CHARTABLE[*token] == LETTER)
- {
- token[3] = '\0';
- if(strlen(token) > 2 && strstr(MONTHSTRING,token))
- {
- number = (strstr(MONTHSTRING,token) - MONTHSTRING) / 3 + 1;
- if(d.da_mon != 0 && d.da_day == 0)
- d.da_day = d.da_mon;
- d.da_mon = (char)number;
- }
- }
- else if(tokench)
- {
- number = atoi(token);
- if(d.da_mon == 0 && number < 13)
- d.da_mon = (char)number;
- else if(d.da_day == 0 && number < 32)
- {
- d.da_day = (char)number;
- }
- else if(d.da_year == 0)
- {
- if(number < 100)
- d.da_year = CENTURY;
- d.da_year += number;
- }
- }
- }
- free(token);
- if(!(IsValidDate(d.da_day,d.da_mon,d.da_year)))
- {
- d.da_day = 0;
- d.da_mon = 0;
- d.da_year = 0;
- }
- return(d);
- } /* end of ParseDate */
-
- void RevVideo(void)
- {
- /*----------------------------------------------------------------------
- ** Swaps foreground and background colors while preserving blink and
- ** high intensity bits.
- **
- ** Note: If the foreground and background colors are the same, this
- ** function will serve no purpose. While it may sound ridiculous
- ** to have the same foreground color as background color, it is
- ** quite possible in the case where the high intensity or blink
- ** foreground bits are set. Setting either of these bits makes
- ** the foreground color viewable on the background color even
- ** though the colors are the same.
- **
- ** Text Color Bit Map:
- ** ┌───┬───┬───┬───╥───┬───┬───┬───┐
- ** │ 7 │ 6 │ 5 │ 4 ║ 3 │ 2 │ 1 │ 0 │
- ** ├───┼───┼───┼───╫───┼───┼───┼───┤
- ** │ I │ b │ b │ b ║ B │ f │ f │ f │
- ** └───┴───┴───┴───╨───┴───┴───┴───┘
- ** f - Foreground
- ** B - Blink
- ** b - Background
- ** I - High Intensity
- **
- ** Uses:
- ** <CONIO.H>
- */
- #define COLORSWAP(b) (((b & 0x08) | ((b & 0x70) >> 4)) | ((b & 0x80) | ((b & 0x07) << 4)))
- struct text_info ti;
-
- gettextinfo(&ti);
- textattr(COLORSWAP(ti.attribute));
- } /* End of RevVideo */
-
- char *WeekdayName(char weekday)
- {
- char *WEEKDAYNAME[] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
- return(WEEKDAYNAME[weekday]);
- } /* end of WeekdayName */
-
- short Calendar(struct date d)
- /*----------------------------------------------------------------------
- ** The calendar function prints a calendar for the specified month.
- **
- ** Blink and background colors have to be shifted 4 bits to the left.
- **
- ** COLORS (text mode)
- ** ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│Back-│Fore-
- ** Constant │Value│grnd?│grnd?
- ** ══════════════╪═════╪═════╪═════
- ** BLACK │ 0 │ Yes │ Yes
- ** BLUE │ 1 │ Yes │ Yes
- ** GREEN │ 2 │ Yes │ Yes
- ** CYAN │ 3 │ Yes │ Yes
- ** RED │ 4 │ Yes │ Yes
- ** MAGENTA │ 5 │ Yes │ Yes
- ** BROWN │ 6 │ Yes │ Yes
- ** LIGHTGRAY │ 7 │ Yes │ Yes
- ** DARKGRAY │ 8 │ No │ Yes
- ** LIGHTBLUE │ 9 │ No │ Yes
- ** LIGHTGREEN │ 10 │ No │ Yes
- ** LIGHTCYAN │ 11 │ No │ Yes
- ** LIGHTRED │ 12 │ No │ Yes
- ** LIGHTMAGENTA │ 13 │ No │ Yes
- ** YELLOW │ 14 │ No │ Yes
- ** WHITE │ 15 │ No │ Yes
- ** ──────────────┼─────┼─────┼──────
- ** BLINK │128 │ No │ ***
- */
- {
- short xpos = wherex(),ypos = wherey(),pos;
- char weekday[4];
- short day = 0;
- short monthColor = LIGHTBLUE,weekColor = GREEN,dayColor = YELLOW;
-
- textcolor(monthColor);
- gotoxy(xpos + ((27 - strlen(MonthName(d.da_mon))) / 2),ypos);
- cprintf("%s",MonthName(d.da_mon));
-
- gotoxy(xpos,++ypos);
- textcolor(weekColor);
- for(pos = 0;pos < 7;pos++)
- {
- strncpy(weekday,WeekdayName(pos),3);
- weekday[3] = '\0';
- cprintf("%s",weekday);
- gotoxy(wherex() + 1,ypos);
- }
-
- gotoxy(++xpos,++ypos);
- textcolor(dayColor);
- for(pos = 1;pos < 38;pos++)
- {
- if(pos > DayOfWeek(1,d.da_mon,d.da_year) && day < DaysInMonth(d.da_mon,d.da_year))
- {
- day++;
- if(day == d.da_day)
- RevVideo();
- cprintf("%02d",day);
- if(day == d.da_day)
- RevVideo();
- gotoxy(wherex() + 2,ypos);
- }
- else
- gotoxy(wherex() + 4,ypos);
- if(!(pos % 7))
- gotoxy(xpos,++ypos);
- }
- gotoxy(--xpos,++ypos);
- return 0;
- } /* end of Calendar */